using System;
using System.Collections.Generic;

namespace LoRel {
    public class IndexBucket {
        private readonly Key m_Key;
        private readonly Dictionary< Key, TableRow > m_AssociatedValues;

        public IndexBucket( Key key ) {
            m_Key = key;
            m_AssociatedValues = new Dictionary< Key, TableRow >();
        }

        public Key Key { get { return m_Key; } }

        public bool TryGet( Key key, out TableRow row ) { return m_AssociatedValues.TryGetValue( key, out row ); }

        public int Count { get { return m_AssociatedValues.Count; } }

        public void EnqueueUpdate( TableChangeArgs args ) {

            FireCoreChangePending( args );

            switch( args.ChangeType ) {
                case ChangeType.Add: Add( args );
                    break;
                case ChangeType.Remove: Remove(args);
                    break;
                case ChangeType.Update: Update( args  );
                    break;
                case ChangeType.Clear: Clear( args  );
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void Add( TableChangeArgs args ) {
            foreach( TableChangeItem item in args.ChangedItems ) {
                m_AssociatedValues.Add( item.NewValue.Key, item.NewValue );
            }
        }
        private void Remove( TableChangeArgs args ) {
            foreach (TableChangeItem item in args.ChangedItems)
            {
                bool success = m_AssociatedValues.Remove( item.OldValue.Key );
                if( ! success ) throw new NotImplementedException("Failure handle");
            }
        }
        private void Update( TableChangeArgs args ) {
            foreach( TableChangeItem item in args.ChangedItems ) {
#if DEBUG
                if( m_AssociatedValues.ContainsKey( item.NewValue.Key ) == false ) {
                    throw new NotImplementedException();
                }
#endif
                m_AssociatedValues[ item.NewValue.Key ] = item.NewValue;
            }
        }
        private void Clear( TableChangeArgs args ) { throw new NotImplementedException(); }


        public void Register( IndexChangeDelegate handler ) {
            List<TableChangeItem> items = new List<TableChangeItem>();
            foreach (KeyValuePair<Key, TableRow> pair in m_AssociatedValues)
            {
                items.Add(new TableChangeItem(pair.Value, null));
            }
            handler(m_Key, new TableChangeArgs(ChangeType.Add, items.Count, items));

            CoreChangePending += handler;
        }
        public void DeRegister( IndexChangeDelegate handler ) {
            CoreChangePending -= handler;
        }

        private void FireCoreChangePending( TableChangeArgs args ) {
            if (CoreChangePending != null) { CoreChangePending( m_Key, args ); }
        }
        private event IndexChangeDelegate CoreChangePending;
        public event IndexChangeDelegate ChangePending { 
            add { Register( value ); } remove { DeRegister( value ); }
        }
    }
}